using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace ZYCommon
{
    public sealed class GraphicsUnitConvert
    {
        private static float fDpi = 96f;

        private GraphicsUnitConvert()
        {
        }

        public static double Convert(double vValue, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return vValue;
            }
            return (vValue * GetRate(NewUnit, OldUnit));
        }

        public static Point Convert(Point p, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return p;
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new Point((int)(p.X * rate), (int)(p.Y * rate));
        }

        public static Rectangle Convert(Rectangle rect, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return rect;
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new Rectangle((int)(rect.X * rate), (int)(rect.Y * rate), (int)(rect.Width * rate), (int)(rect.Height * rate));
        }

        public static RectangleF Convert(RectangleF rect, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return rect;
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new RectangleF((float)(rect.X * rate), (float)(rect.Y * rate), (float)(rect.Width * rate), (float)(rect.Height * rate));
        }

        public static Size Convert(Size size, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return size;
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new Size((int)(size.Width * rate), (int)(size.Height * rate));
        }

        public static SizeF Convert(SizeF size, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return size;
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new SizeF((float)(size.Width * rate), (float)(size.Height * rate));
        }

        public static int Convert(int vValue, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return vValue;
            }
            return (int)(vValue * GetRate(NewUnit, OldUnit));
        }

        public static float Convert(float vValue, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return vValue;
            }
            return (float)(vValue * GetRate(NewUnit, OldUnit));
        }

        public static Point Convert(int x, int y, GraphicsUnit OldUnit, GraphicsUnit NewUnit)
        {
            if (OldUnit == NewUnit)
            {
                return new Point(x, y);
            }
            double rate = GetRate(NewUnit, OldUnit);
            return new Point((int)(x * rate), (int)(y * rate));
        }

        public static double GetDpi(GraphicsUnit unit)
        {
            switch (unit)
            {
                case GraphicsUnit.Display:
                    return (double)fDpi;

                case GraphicsUnit.Pixel:
                    return (double)fDpi;

                case GraphicsUnit.Point:
                    return 72.0;

                case GraphicsUnit.Inch:
                    return 1.0;

                case GraphicsUnit.Document:
                    return 300.0;

                case GraphicsUnit.Millimeter:
                    return 25.4;
            }
            return fDpi;
        }

        public static double GetRate(GraphicsUnit NewUnit, GraphicsUnit OldUnit)
        {
            return (GetUnit(OldUnit) / GetUnit(NewUnit));
        }

        private static double GetUnit(GraphicsUnit unit)
        {
            switch (unit)
            {
                case GraphicsUnit.Display:
                    return (double)(1f / fDpi);

                case GraphicsUnit.Pixel:
                    return (double)(1f / fDpi);

                case GraphicsUnit.Point:
                    return 0.013888888888888888;

                case GraphicsUnit.Inch:
                    return 1.0;

                case GraphicsUnit.Document:
                    return 0.0033333333333333335;

                case GraphicsUnit.Millimeter:
                    return 0.03937007874015748;
            }
            throw new NotSupportedException("Not support " + unit.ToString());
        }

        public static float Dpi
        {
            get
            {
                return fDpi;
            }
            set
            {
                fDpi = value;
            }
        }
    }
}
